home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / libsipp / pixel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-03  |  5.9 KB  |  246 lines

  1. /**
  2.  ** sipp - SImple Polygon Processor
  3.  **
  4.  **  A general 3d graphic package
  5.  **
  6.  **  Copyright Equivalent Software HB  1992
  7.  **
  8.  ** This program is free software; you can redistribute it and/or modify
  9.  ** it under the terms of the GNU General Public License as published by
  10.  ** the Free Software Foundation; either version 1, or any later version.
  11.  ** This program is distributed in the hope that it will be useful,
  12.  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  ** GNU General Public License for more details.
  15.  ** You can receive a copy of the GNU General Public License from the
  16.  ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  **/
  18.  
  19. /**
  20.  ** pixel.c - Functions that handle the pixel buffer
  21.  **/
  22.  
  23.  
  24. #include <sipp.h>
  25. #include <smalloc.h>
  26. #include <pixel.h>
  27.  
  28.  
  29. /*
  30.  * Background color.
  31.  */
  32. Color sipp_bgcol;
  33.  
  34.  
  35. /*
  36.  * Entry in a position in the pixel buffer.
  37.  */
  38. typedef struct {
  39.     Color          color;
  40.     Color          opacity;
  41.     double         depth;
  42.     int            next;
  43. } Pixel_info;
  44.  
  45.  
  46. static int          pixbuf_size;     /* Current size of pixel buffer */
  47. static int          size_delta;      /* How much to realloc each time */
  48. static Pixel_info  *pixbuf = 0;      /* The actual pixel buffer */
  49. static int          first_free;      /* First free Pixel_info in the buffer */
  50.  
  51.  
  52.  
  53. /*
  54.  * Initialize the pixel buffer.
  55.  */
  56. void
  57. pixels_setup(init_size)
  58.     int init_size;
  59. {
  60.     if (pixbuf != 0) {
  61.         sfree(pixbuf);        /* Just in case */
  62.     }
  63.  
  64.     pixbuf = (Pixel_info *)scalloc(init_size, sizeof(Pixel_info));
  65.     pixbuf_size = init_size;
  66.     pixels_reinit();
  67.     size_delta = init_size / 2;
  68. }
  69.  
  70.  
  71. /*
  72.  * Free memory used by pixel_buffer.
  73.  */
  74. void
  75. pixels_free()
  76. {
  77.     sfree(pixbuf);
  78.     pixbuf = 0;
  79. }
  80.  
  81.  
  82. /*
  83.  * Renitialize the free_list.
  84.  */
  85. void
  86. pixels_reinit()
  87. {
  88.     first_free = 0;
  89. }
  90.     
  91.  
  92. /*
  93.  * Allocate a Pixel_info struct from the free list.
  94.  * Realloc a larger pixbuf if needed.
  95.  */
  96. static int
  97. pixel_alloc()
  98. {
  99.     if (first_free == pixbuf_size) {
  100.         pixbuf_size += size_delta;
  101.         pixbuf = (Pixel_info *)srealloc(pixbuf, 
  102.                                         pixbuf_size * sizeof(Pixel_info));
  103.     }
  104.  
  105.     pixbuf[first_free].next = -1;
  106.     first_free++;
  107.     return (first_free - 1);
  108. }
  109.     
  110.  
  111. /*
  112.  * Check if a polygon at DEPTH is possibly visible in PIXEL
  113.  */
  114. bool
  115. pixel_visible(depth, pixel)
  116.     double     depth;
  117.     int        pixel;
  118. {
  119.     Color opacity_sum;
  120.  
  121.     opacity_sum.red = 0.0;
  122.     opacity_sum.grn = 0.0;
  123.     opacity_sum.blu = 0.0;
  124.  
  125.     while (pixel != -1) {
  126.         if (depth < pixbuf[pixel].depth) {
  127.             return TRUE;
  128.         }
  129.         opacity_sum.red += pixbuf[pixel].opacity.red;
  130.         opacity_sum.grn += pixbuf[pixel].opacity.grn;
  131.         opacity_sum.blu += pixbuf[pixel].opacity.blu;
  132.         if (opacity_sum.red < 1.0 || opacity_sum.grn < 1.0 
  133.             || opacity_sum.grn < 1.0) {
  134.             pixel = pixbuf[pixel].next;
  135.         } else {
  136.             return FALSE;
  137.         }
  138.     }
  139.  
  140.     return TRUE;
  141. }
  142.  
  143.     
  144. /*
  145.  * Create a new Pixel_info struct containing DEPTH, COLOR and OPACITY and
  146.  * insert it into PIXEL.
  147.  */
  148. int
  149. pixel_insert(pixel, depth, color, opacity)
  150.     int      pixel;
  151.     double   depth;
  152.     Color   *color;
  153.     Color   *opacity;
  154. {
  155.     int  pixref1;
  156.     int  pixref2;
  157.     int  tmp;
  158.  
  159.     tmp = pixel_alloc();
  160.     pixbuf[tmp].depth = depth;
  161.     pixbuf[tmp].color = *color;
  162.     pixbuf[tmp].opacity = *opacity;
  163.  
  164.     if (pixel == -1) {
  165.         return tmp;
  166.     } else if (depth < pixbuf[pixel].depth) {
  167.         pixbuf[tmp].next = pixel;
  168.         return tmp;
  169.     } else {
  170.         pixref1 = pixel;
  171.         pixref2 = pixbuf[pixel].next;
  172.         while (pixref2 != -1 && pixbuf[pixref2].depth < depth) {
  173.             pixref1 = pixref2;
  174.             pixref2 = pixbuf[pixref2].next;
  175.         } 
  176.         pixbuf[pixref1].next = tmp;
  177.         pixbuf[tmp].next = pixref2;
  178.         return pixel;
  179.     }
  180. }
  181.  
  182.  
  183. /*
  184.  * Sum the resulting color in a pixel and store it
  185.  * in the first Pixel_info in the list (if there is one).
  186.  * Return a pointer to this color, or NULL if there is no color.
  187.  */
  188. Color *
  189. pixel_collect(pixel)
  190.     int  pixel;
  191. {
  192.     Color    result;
  193.     Color    frac;
  194.     Color    opacity_sum;
  195.     int      pixref;
  196.     bool     pixel_full;
  197.  
  198.     result.red = result.grn = result.blu = 0.0;
  199.     opacity_sum.red = opacity_sum.grn = opacity_sum.blu = 0.0;
  200.  
  201.     pixref = pixel;
  202.     pixel_full = FALSE;
  203.  
  204.     while (pixref != -1) {
  205.         frac.red = pixbuf[pixref].opacity.red;
  206.         if (frac.red + opacity_sum.red > 1.0) {
  207.             frac.red = 1.0 - opacity_sum.red;
  208.         }
  209.         frac.grn = pixbuf[pixref].opacity.grn;
  210.         if (frac.grn + opacity_sum.grn > 1.0) {
  211.             frac.grn = 1.0 - opacity_sum.grn;
  212.         }
  213.         frac.blu = pixbuf[pixref].opacity.blu;
  214.         if (frac.blu + opacity_sum.blu > 1.0) {
  215.             frac.blu = 1.0 - opacity_sum.blu;
  216.         }
  217.         result.red += frac.red * pixbuf[pixref].color.red;
  218.         result.grn += frac.grn * pixbuf[pixref].color.grn;
  219.         result.blu += frac.blu * pixbuf[pixref].color.blu;
  220.         opacity_sum.red += frac.red;
  221.         opacity_sum.grn += frac.grn;
  222.         opacity_sum.blu += frac.blu;
  223.         if (opacity_sum.red >= 1.0 && opacity_sum.grn >= 1.0 
  224.             && opacity_sum.blu >= 1.0) {
  225.             pixel_full = TRUE;
  226.             break;
  227.         }
  228.         pixref = pixbuf[pixref].next;
  229.     }
  230.  
  231.     if (pixel != -1) {
  232.         if (!pixel_full) {
  233.             result.red += ((opacity_sum.red >= 1.0) 
  234.                            ? 0.0 : 1.0 - opacity_sum.red) * sipp_bgcol.red; 
  235.             result.grn += ((opacity_sum.grn >= 1.0) 
  236.                            ? 0.0 : 1.0 - opacity_sum.grn) * sipp_bgcol.grn; 
  237.             result.blu += ((opacity_sum.blu >= 1.0) 
  238.                            ? 0.0 : 1.0 - opacity_sum.blu) * sipp_bgcol.blu; 
  239.         }
  240.         pixbuf[pixel].color = result;
  241.         return &pixbuf[pixel].color;
  242.     } else {
  243.         return &sipp_bgcol;
  244.     }
  245. }
  246.